模块化方面,提供模块加载方案,并兼容不同的模块规范。
语法转译方面,配合 Sass、TSC、Babel 等前端工具链,完成高级语法的转译功能,同时对于静态资源也能进行处理,使之能作为一个模块正常加载。
产物质量方面,在生产环境中,配合 Terser等压缩工具进行代码压缩和混淆,通过 Tree Shaking 删除未使用的代码,提供对于低版本浏览器的语法降级处理等等。
开发效率方面,构建工具本身通过各种方式来进行性能优化,包括使用原生语言 Go/Rust、no-bundle等等思路,提高项目的启动性能和热更新的速度。
一般的项目使用 Webpack 之后,启动花个几分钟都是很常见的事情,热更新也经常需要等待十秒以上。这主要是因为:
项目冷启动时必须递归打包整个项目的依赖树JavaScript 语言本身的性能限制,导致构建性能遇到瓶颈,直接影响开发效率Vite 很好地解决了这些问题。
Vite 在开发阶段基于浏览器原生 ESM 的支持实现了no-bundle服务借助 Esbuild 超快的编译速度来做第三方库构建和 TS/JSX 语法编译,从而能够有效提高开发效率模块化方面,Vite 基于浏览器原生 ESM 的支持实现模块加载,并且无论是开发环境还是生产环境,都可以将其他格式的产物(如 CommonJS)转换为 ESM。
语法转译方面,Vite 内置了对 TypeScript、JSX、Sass 等高级语法的支持,也能够加载各种各样的静态资源,如图片、Worker 等等。
产物质量方面,Vite 基于成熟的打包工具 Rollup 实现生产环境打包,同时可以配合Terser、Babel等工具链,可以极大程度保证构建产物的质量。
2、前端三大模块规范:CommonJS、AMD 和 ES Module2-1、无模块化标准阶段1、文件划分:将应用的状态和逻辑分散到不同的文件中,然后通过 script 引入。
// module-a.jslet data = "data";// index.html2、命名空间:可以解决 文件划分 带来的全局变量定义所带来的问题,变量冲突以及变量作用域不明确等。
// module-a.jswindow.moduleA = { data: "moduleA", method: function () {console.log("execute A's method"); },};3、立即执行函数(IIFE):模块化安全性更高,对于模块作用域的区分更加彻底。
立即执行函数会创建一个私有的作用域,在私有作用域中的变量外界是无法访问到的,只有在模块内部可以访问到。
// module-a.js(function () { let data = "moduleA"; function method() {console.log(data + "execute"); } window.moduleA = {method: method, };})();// index.html弊端:如果模块间存在依赖关系,那么script标签的加载顺序就需要受到严格的控制。
2-2、CommonJS 规范对于模块规范而言,一般会包含两个内容:
统一的模块化代码规范实现自动加载模块的加载器(loader)使用 require 来导入一个模块,用 module.exports 来导出一个模块。
存在的问题:
模块加载器由 Node.js 提供,依赖了 Node.js 本身的功能实现,比如文件系统,如果 CommonJS 模块直接放到浏览器中是无法执行的。当然, 业界也产生了 browserify 这种打包工具来支持打包 CommonJS 模块,从而顺利在浏览器中执行,相当于社区实现了一个第三方的 loader。CommonJS 本身约定以同步的方式进行模块加载,这种加载机制放在服务端是没问题的。但如果这种加载机制放到浏览器端,会带来明显的性能问题。它会产生大量同步的模块请求,浏览器要等待响应返回后才能继续解析模块。也就是说,模块请求会造成浏览器 JS 解析过程的阻塞,导致页面加载速度缓慢。2-3、AMD 规范AMD全称为Asynchronous Module Definition,即异步模块定义规范。
存在的问题:
没有得到浏览器的原生支持,AMD 规范需要由第三方的 loader 来实现,最经典的就是 requireJS 库了代码阅读和书写都比较困难2-4、ES6 Module由 ECMAScript 官方提出的模块化规范,作为一个官方提出的规范,ES Module 已经得到了现代浏览器的内置支持。
在现代浏览器中,如果在 HTML 中加入含有type="module"属性的 script 标签,那么浏览器会按照 ES Module 规范来进行依赖加载和模块解析,这也是 Vite 在开发阶段实现 no-bundle 的原因,由于模块加载的任务交给了浏览器,即使不打包也可以顺利运行模块代码。
如今的ES Module可以同时在浏览器与Node.js(12版本及以上)环境中执行,拥有天然的跨平台的能力。
2-5、总结:文件划分没有解决变量冲突的问题,命名空间和IIFE虽然解决了变量冲突但是没有解决模块间的依赖问题。CommonJS规范适用于服务端,在浏览器端没有原生支持,并且因为需要同步模块资源,会阻塞页面解析;AMD、CMD等异步加载方案,也没有浏览器原生支持,使用方式稍显复杂;ESModule方案使用简单,并且大多数浏览器都原生支持,设置在Node环境下也可以运行,是主流的前端模块化方案。3、vite从0开始搭建前端项目命令:
pnpm create viteVite 默认会把项目根目录下的index.html作为入口文件。也就是说,当你访问http://localhost:3000的时候,Vite 的 Dev Server 会自动返回这个 HTML 文件的内容。
index.html:在 body 标签中除了 id 为 root 的根节点之外,还包含了一个